using TrackSystem.Entities.Extensions;
using TrackSystem.IO.Alarm;
using TrackSystem.IO.Data;
using TrackSystem.IO.Models;

namespace TrackSystem.IO.Protocol
{
    /// <summary>
    /// 姿态传感器
    /// 0 - picth
    /// 1 - roll
    /// 2 - heading
    /// </summary>
    public class LEC210Protocl : ProtocolBase
    {
        private int startTicks;
        private int repeatTimes;    //写入操作重复次数

        private readonly int roLength;
        private readonly int rwLength;

        private byte[] Tx_r2;       //校准
        private byte[] Tx_r3;       //停止校准
        bool calibrating;          // 是否正在校准
        bool stopCalibrating;      // 是否要停止校准
        private bool bSendR, bSendW;     // 发送标志

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="name"></param>
        public LEC210Protocl(string name, int roLength,  int rwLength)
            : base()
        {
            NeedInit = true; // 初始化写入寄存器  
            calibrating = false;
            stopCalibrating = false;
            Name = name;
            this.roLength = roLength;
            this.rwLength = rwLength;
            Tx_r = new byte[5] {0x77, 0x04, 0x00, 0x04, 0x08};
            Tx_r2 = new byte[5] { 0x77, 0x04, 0x00, 0x08, 0x0C }; //校准
            Tx_r3 = new byte[5] { 0x77, 0x04, 0x00, 0x09, 0x0D }; //停止校准

            bSendR = false;
            bSendW = false;
        }

        /// <summary>
        /// 生成读取寄存器的通讯帧
        /// </summary>
        /// <returns></returns>
        public override byte[] GenerateReadFrame(out int NeedRecvLen)
        {
            startTicks = Environment.TickCount;
            NeedRecvLen = 8;
            //if (calibrating || stopCalibrating)
            //{
            //    Fail_R--;
            //}
            if (calibrating)
            {
                NeedRecvLen = 0;
                return null;
            }
            else if (stopCalibrating) {
                stopCalibrating = false;
                NeedRecvLen = 0;
                return null;
            }
            // 上次的发送没有收到正确回复，bSend没有被置位
            if (bSendR)
            {
                Fail_R++;
                // 失败超过3次，成功次数清零
                if (Fail_R >= 3)
                {
                    Succ_R = 0;
                }
            }
            bSendR = true;
            return Tx_r;
        }


        /// <summary>
        /// 根据收到的内容进行处理
        /// </summary>
        /// <param name="buffer"></param>
        /// <returns></returns>
        public override bool ProcessReadFrame(byte[] buffer)
        {
            Rx_r = buffer;
            Lapse = Environment.TickCount - startTicks;
            if (NeedInit) {
                RegFactory.Instance.SetVal(RegNameList[3], 0);
                RegFactory.Instance.SetVal(RegNameList[4], 0);
                NeedInit = false;
            }
            if (buffer[0] != 0x77 || buffer[1] != 0x0D || buffer[2] != 0x00){
                return false;
            }

            if (buffer[3] == 0x84) {
                int bit1 = (buffer[4] & 0xFF) >> 4;
                int bit2 = buffer[4] & 0x0F;
                int bit3 = ((buffer[5] & 0xFF) >> 4) * 10 + (buffer[5] & 0x0F);
                int bit4 = ((buffer[6] & 0xFF) >> 4) * 10 + (buffer[6] & 0x0F);
                double val_pitch = bit2 * 100 + bit3 + bit4 * 0.01;
                if (bit1 == 1) {
                    val_pitch = -val_pitch;
                }
                int bit5 = (buffer[7] & 0xFF) >> 4;
                int bit6 = buffer[7] & 0x0F;
                int bit7 = ((buffer[8] & 0xFF) >> 4) * 10 + (buffer[8] & 0x0F);
                int bit8 = ((buffer[9] & 0xFF) >> 4) * 10 + (buffer[9] & 0x0F);
                double val_roll = bit6 * 100 + bit7 + bit8 * 0.01;
                if (bit5 == 1)
                    val_roll = -val_roll;
                int bit9 = (buffer[10] & 0xFF) >> 4;
                int bit10 = buffer[10] & 0x0F;
                int bit11 = ((buffer[11] & 0xFF) >> 4) * 10 + (buffer[11] & 0x0F);
                int bit12 = ((buffer[12] & 0xFF) >> 4) * 10 + (buffer[12] & 0x0F);
                double val_heading = bit10 * 100 + bit11 + bit12 * 0.01;
                if (bit9 == 1)
                    val_heading = -val_heading;
                RegFactory.Instance.SetVal(RegNameList[0], val_pitch);
                RegFactory.Instance.SetVal(RegNameList[1], val_roll);
                RegFactory.Instance.SetVal(RegNameList[2], val_heading);
                Succ_R++;
                bSendR = false;     // 正确收到，标志位变为false
                Fail_R = 0;         // 通信成功，则将失败次数清零
            }
            return true;
        }


        /// <summary>
        /// 生成写入寄存器的通讯帧
        /// </summary>
        /// <param name="NeedRecvLen"></param>
        /// <returns></returns>
        public override byte[] GenerateWriteFrame(out int NeedRecvLen)
        {
            startTicks = Environment.TickCount;
            // 待写入的数据队列非空 
            if (writeQueue.Count() > 0)
            {
                repeatTimes = 3;    // 写入的重复次数更新为3次
            }
            // 生成写入数据帧
            if (WriteFlag && repeatTimes-- > 0)
            {
                while (writeQueue.TryDequeue(out AddressAndVal data))
                {
                    if (data.Address == 0 && data.Value == 1)
                    {
                        calibrating = true;
                        Tx_w = Tx_r2;
                        //break;
                    }
                    else if (data.Address == 1 && data.Value == 1)
                    {
                        Tx_w = Tx_r3;
                        //break;
                    }
                }
                // 上次没有收到正确的返回帧
                if (bSendW)
                {
                    Fail_W++;
                    Succ_W = 0;
                }
                bSendW = true;
                NeedRecvLen = 4;
                return Tx_w;
            }

            // 如果写入次数超过三次未成功，则将队列清空
            if (repeatTimes <= 0)
            {
                AlarmFactory.Instance.Insert("Write data error, more than three attempts",
                    AlarmCategory.COMM, Name, 0);

                // 标志位复位 重启下一个批次的读写任务
                WriteFlag = false;
            }
            NeedRecvLen = 8;
            return null;
        }

        /// <summary>
        /// 根据收到的内容进行处理
        /// </summary>
        /// <param name="buffer"></param>
        /// <returns></returns>
        public override bool ProcessWriteFrame(byte[] buffer)
        {
            Lapse = Environment.TickCount - startTicks;

            int nLen = buffer.Length;
            Rx_w = buffer;

            if (buffer[1] == 0x05 && buffer[3] == 0x88)
            {
                RegFactory.Instance.SetVal(RegNameList[3], 1);
                RegFactory.Instance.SetVal(RegNameList[4], 0);
            } else if (buffer[1] == 0x05 && buffer[3] == 0x89) {
                RegFactory.Instance.SetVal(RegNameList[4], 1);
                RegFactory.Instance.SetVal(RegNameList[3], 0);
                calibrating = false;
                stopCalibrating = true;
            }

            Succ_W++;
            bSendW = false;
            Fail_W = 0;  // 通信成功，则将失败次数清零

            WriteFlag = false;
            repeatTimes = 0;
            return true;
        }

        /// <summary>
        /// 改变变量的值
        /// </summary>
        /// <param name="Index"></param>
        /// <param name="Value"></param>
        public override void PushRegValue(int Index, double Value)
        {
            Index -= roLength;  //寄存器存储顺序从0开始，先是只读存储器，后面是读写存储器

            if (Index >= 0 && (Index < rwLength))
            {
                writeQueue.Enqueue(new AddressAndVal(Index, Value));
                WriteFlag = true;
            }
        }
    }
}

